import 'dart:async';
import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_lui/flutter_lui.dart';

/// 屏幕适配尺寸
///
/// 在LUI的单例中设置设计图尺寸后，每个需要宽度或高度的数值使用rpx(数值) 可以得到适配各个屏幕的尺寸
double rpx(double size) {
  return size * PageSize.sizeRatio;
}

class PageSize {
  static final MediaQueryData mediaQueryData =
      MediaQueryData.fromWindow(window);
  static var baseScreenWidth = LUI.instance.baseDesignWidth;
  static var sizeRatio = mediaQueryData.size.width / baseScreenWidth;
  static final double statusBarHeight = mediaQueryData.padding.top;
  static const double titleBarHeight = kToolbarHeight;
  static const double bottomBarHeight = kBottomNavigationBarHeight;
  static final double width = mediaQueryData.size.width;
  static final double height = mediaQueryData.size.height;
  static final double safeAreaHeight = mediaQueryData.padding.bottom;
}

/// 延迟执行
/// - @params ms 毫秒
Future<void> delay(int ms) {
  Completer c = Completer();
  Timer(Duration(milliseconds: ms), () => c.complete());
  return c.future;
}

/// 获取列表中第一个满足条件的元素
T? firstWhereOrNull<T>(List<T> list, bool Function(T t) callBack) {
  T? res;
  try {
    res = list.firstWhere(callBack);
  } catch (e) {
    return null;
  }
  return res;
}

/// 根据长度产生随机数
///
/// 默认不包含特殊字符
///
String randomString(
  int len, {
  /// 是否不包含大写字母
  bool? noUpperCase,

  /// 是否不包含小写字母
  bool? noLowerCase,

  /// 是否不包含数字
  bool? noNumber,

  /// 是否不包含特殊字符
  bool? noSymbol = true,

  /// 自定义字符
  String? freeChars,
}) {
  var upChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  var lowChars = 'abcdefghijklmnopqrstuvwxyz';
  var numChars = '1234567890';
  var symbolChars = r'~!@#$%^&*()-+|?><,./;\{}[]';
  var chars = '';
  if (noUpperCase != true) {
    chars += upChars;
  }
  if (noLowerCase != true) {
    chars += lowChars;
  }
  if (noNumber != true) {
    chars += numChars;
  }
  if (noSymbol != true) {
    chars += symbolChars;
  }
  if (freeChars?.isNotEmpty == true) {
    chars += freeChars!;
  }

  var maxpos = chars.length;
  var str = '';
  for (var i = 0; i < len; i++) {
    str += chars[(Random().nextInt(maxpos))];
  }
  return str;
}

/// 验证手机号
bool validateTel(String? tel) {
  return RegExp(r'^1[3456789]\d{9}$').hasMatch(tel ?? '');
}

/// 验证身份证号
bool validateCardId(String cardId) {
  if (cardId.length != 18) {
    return false; // 位数不够
  }
// 身份证号码正则
  RegExp postalCode = RegExp(
      r'^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|[Xx])$');
// 通过验证，说明格式正确，但仍需计算准确性
  if (!postalCode.hasMatch(cardId)) {
    return false;
  }
//将前17位加权因子保存在数组里
  final List idCardList = [
    "7",
    "9",
    "10",
    "5",
    "8",
    "4",
    "2",
    "1",
    "6",
    "3",
    "7",
    "9",
    "10",
    "5",
    "8",
    "4",
    "2"
  ];
//这是除以11后，可能产生的11位余数、验证码，也保存成数组
  final List idCardYArray = [
    '1',
    '0',
    '10',
    '9',
    '8',
    '7',
    '6',
    '5',
    '4',
    '3',
    '2'
  ];
// 前17位各自乖以加权因子后的总和
  int idCardWiSum = 0;

  for (int i = 0; i < 17; i++) {
    int subStrIndex = int.parse(cardId.substring(i, i + 1));
    int idCardWiIndex = int.parse(idCardList[i]);
    idCardWiSum += subStrIndex * idCardWiIndex;
  }
// 计算出校验码所在数组的位置
  int idCardMod = idCardWiSum % 11;
// 得到最后一位号码
  String idCardLast = cardId.substring(17, 18);
//如果等于2，则说明校验码是10，身份证号码最后一位应该是X
  if (idCardMod == 2) {
    if (idCardLast != 'x' && idCardLast != 'X') {
      return false;
    }
  } else {
    //用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
    if (idCardLast != idCardYArray[idCardMod]) {
      return false;
    }
  }
  return true;
}

List<T?> findTRBL<T>(List<T> list) {
  T? pt, pb, pl, pr;
  if (list.length == 1) {
    pt ??= list[0];
    pr ??= list[0];
    pb ??= list[0];
    pl ??= list[0];
  } else if (list.length == 2) {
    pt ??= list[0];
    pr ??= list[1];
    pb ??= list[0];
    pl ??= list[1];
  } else if (list.length == 3) {
    pt ??= list[0];
    pr ??= list[1];
    pb ??= list[2];
    pl ??= list[1];
  } else if (list.length >= 4) {
    pt ??= list[0];
    pr ??= list[1];
    pb ??= list[2];
    pl ??= list[3];
  }

  zeroToNull(t) {
    if (t != null && t != 0 && t != '') return t;
    return null;
  }

  return [zeroToNull(pt), zeroToNull(pr), zeroToNull(pb), zeroToNull(pl)];
}
